﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Licensed MIT: http://www.opensource.org/licenses/mit-license.php

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using DNA.OpenAPI.Ping;

namespace DNA.Mvc.Publishing.Observers
{
    public class PingObserver : EventTypebaseObserver<ArticleUpdateEvent>
    {
        private string webTitle = "";
        public override void Process(ArticleUpdateEvent e)
        {
            if ((e.Article != null) && (e.Article.IsPublished) && (!string.IsNullOrEmpty(e.Article.PingUrls)))
            {
                //webTitle = e.Web.Title;
                PingOnBackground(new ArticleWrapper(e.Article));
            }
        }

        private void PingOnBackground(ArticleWrapper article)
        {
            var urls = article.GetPingUrls();// new List<Uri>();
            //var strUrls = article.GetPingUrls();

            foreach (var url in urls)
            {
                try
                {
                    var request = (HttpWebRequest)WebRequest.Create(url);
                    request.Headers["Accept-Encoding"] = "gzip";
                    request.Headers["Accept-Language"] = "en-us";
                    request.Credentials = CredentialCache.DefaultNetworkCredentials;
                    request.AutomaticDecompression = DecompressionMethods.GZip;
                    var state = new Dictionary<string, object>();
                    state.Add("request", request);
                    state.Add("permalink", article.PermaLink);
                    state.Add("msg", GetTrackbackMessage(article, new Uri(url)));
                    request.BeginGetResponse(new AsyncCallback(PingAsync), state);
                }
                catch (Exception e)
                {
                    OnError(e);
                    continue;
                }
            }
        }

        private void PingAsync(IAsyncResult result)
        {
            try
            {
                var state = (Dictionary<string, object>)result.AsyncState;
                var request = (HttpWebRequest)state["request"];
                var permalink = (string)state["permalink"];
                var trackbackmsg = (TrackbackMessage)state["msg"];
                var response = request.EndGetResponse(result);

                using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
                {
                    string content = reader.ReadToEnd();
                    string contentType = response.ContentType;
                    Uri uri = null;

                    #region check the target uri is pingable
                    var pingUrlKeyIndex = Array.FindIndex(response.Headers.AllKeys,
                                delegate(string k)
                                {
                                    return k.Equals("x-pingback", StringComparison.OrdinalIgnoreCase) ||
                                           k.Equals("pingback", StringComparison.OrdinalIgnoreCase);
                                });

                    if (pingUrlKeyIndex != -1)
                        Uri.TryCreate(response.Headers[pingUrlKeyIndex], UriKind.Absolute, out uri);
                    //If the resource is resource ping enabled
                    if (uri != null)
                    {
                        PingbackSender.Send(new Uri(permalink), request.RequestUri, uri);
                        return;
                    }

                    #endregion

                    if (contentType.StartsWith("image", StringComparison.OrdinalIgnoreCase) ||
    contentType.StartsWith("media", StringComparison.OrdinalIgnoreCase))
                        return;

                    uri = UrlUtility.GetTrackBackUrlFromContent(content);
                    if (uri != null)
                    {
                        if (!uri.ToString().Equals(permalink, StringComparison.OrdinalIgnoreCase))
                        {
                            trackbackmsg.DestinationUrl = uri;
                            TrackbackSender.Send(trackbackmsg);
                        }
                    }
                    else
                    {
                        uri = UrlUtility.GetPingbackUrlFromContent(content);
                        if (uri != null)
                            PingbackSender.Send(new Uri(permalink), request.RequestUri, uri);
                    }
                }
            }
            catch
            {
            }
        }

        private TrackbackMessage GetTrackbackMessage(ArticleWrapper article, Uri uri)
        {
            string excerpt = article.Summary;
            if (string.IsNullOrEmpty(excerpt))
            {
                excerpt = TextUtility.ClearHtml(article.Body);
                if (excerpt.Length > 100)
                {
                    excerpt = excerpt.Substring(0, 100);
                }
            }

            return new TrackbackMessage()
            {
                BlogTitle = webTitle,
                DestinationUrl = uri,
                Excerpt = excerpt,
                Title = article.Title,
                UrlToNotifyTrackback = new Uri(article.PermaLink)
            };
        }
    }
}
